package com.ctl.lib_common.utils.http

import android.util.LruCache
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.Utils
import com.ctl.lib_common.BuildConfig
import com.ctl.lib_common.base.BaseConstants
import com.ctl.lib_common.utils.LocalCache
import com.ctl.lib_common.utils.livebus.LiveBus
import okhttp3.Cache
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.io.UnsupportedEncodingException
import java.net.URLDecoder
import java.util.concurrent.TimeUnit

/**
 * @description: 网络请求工具
 */
object HttpEngine {
    private const val DEFAULT_CONNECT_TIME = 10L
    private const val DEFAULT_WRITE_TIME = 30L
    private const val DEFAULT_READ_TIME = 30L
    private const val CACHE_SERVICE_COUNT = 100

    private lateinit var defaultRetrofit: Retrofit
    private var defaultOkHttpClient: OkHttpClient
    private var serviceCache: LruCache<String, Any>

    init {
        val loggingInterceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
            override fun log(message: String) {
                try {
                    val result = if (message.contains("%")) {
                        message.replace("%(?![0-9a-fA-F]{2})".toRegex(), "%25")
                    } else {
                        message
                    }
                    val msg = URLDecoder.decode(result, "utf-8")
                    if (msg.startsWith("{") && msg.endsWith("}")) {
                        LogUtils.e("OKHttp======>$msg")
                    }
                } catch (e: UnsupportedEncodingException) {
                    e.printStackTrace()
                    LogUtils.e("OKHttp======>${message}")
                }
            }
        })
        if (BuildConfig.DEBUG) {
            loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        } else {
            loggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
        }
        val mTokenInterceptor = object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                val request = chain.request()
                val builder = request.newBuilder()
                    .addHeader(
                        "Authorization",
                        "${LocalCache.getInstance()
                            .getString(BaseConstants.LOCAL_CACHE_MW_UID)} ${LocalCache.getInstance()
                            .getString(BaseConstants.LOCAL_CACHE_MW_TOKEN)}"
                    ).build()
                val response = chain.proceed(builder)
                if (response.code == 401) {
                    LiveBus.get(BaseConstants.LIVE_BUS_GOTO_WM_LOGIN).post(401)
                }
                return response
            }
        }
        defaultOkHttpClient = OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .addInterceptor(mTokenInterceptor)
            .connectTimeout(DEFAULT_CONNECT_TIME, TimeUnit.SECONDS)// 连接超时时间
            .writeTimeout(DEFAULT_WRITE_TIME, TimeUnit.SECONDS)// 设置写操作超时时间
            .readTimeout(DEFAULT_READ_TIME, TimeUnit.SECONDS)// 设置读操作超时时间
            .retryOnConnectionFailure(true)
            .cache(
                Cache(
                    File(Utils.getApp().cacheDir.toString() + "HttpCache"),
                    1024L * 1024 * 100
                )
            )
            .build()
        serviceCache = LruCache(CACHE_SERVICE_COUNT)
    }

    fun buildRetrofit(baseUrl: String) {
        defaultRetrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(defaultOkHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build()
        serviceCache.evictAll()
    }

    fun <T> getService(service: Class<T>): T {
        var retrofitService: T? = serviceCache.get(service.canonicalName) as T
        if (retrofitService == null) {
            retrofitService = defaultRetrofit.create(service)
            serviceCache.put(service.canonicalName, retrofitService)
        }
        return retrofitService!!
    }
}